﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////


#include "GnufFamilyTreeNodeUtil.h"
#include "CommandParameters.h"
#include "GbmpCommandNames.h"
#include "GnufInfo.h"
#include "GnufTree.h"
#include "ICommandManager.h"
#include "IFamilyConfigElement.h"
#include "IJournalCommandData.h"
#include "IUiDocument.h"
#include "IUiDocumentViewManager.h"
#include "JournalUtils.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

#define ICON_FamilyManagerRootItem  L":/image/ModelView/FamilyTree/FamilyManagerRootItem"
#define ICON_FamilyCategory         L":/image/ModelView/FamilyTree/FamilyCategory"
#define ICON_Family                 L":/image/ModelView/FamilyTree/Family"
#define ICON_FamilyType             L":/image/ModelView/FamilyTree/FamilyType"
#define ICON_FamilyLoading          L":/image/ModelView/FamilyTree/FamilyLoading"
#define ICON_ImportedObject         ICON_FamilyLoading
#define ICON_CADSheetCategory       ICON_FamilyCategory
#define ICON_ImportCAD              L":/image/ModelView/FamilyTree/ImportCAD"
#define ICON_CADSheet               ICON_ImportCAD

using namespace gcmp;
using namespace gfam;
using namespace gnuf;

//////////////////////////////////////////////////////////////////////////
/// GnufFamilyTreeNodeUtil implement

const std::wstring FAMILY_TEXT = GBMP_TR(L"构件");
const std::wstring IMPORTED_OBJ_TEXT = GBMP_TR(L"导入对象");
const std::wstring CAD_SHEET_CATEGORY_TEXT = GBMP_TR(L"图纸");
const std::wstring SAT_SHEET_CATEGORY_TEXT = GBMP_TR(L"SAT文件");

std::wstring GnufFamilyTreeNodeUtil::GetIconPathForFamilyRootItem()
{
    return ICON_FamilyManagerRootItem;
}

std::wstring GnufFamilyTreeNodeUtil::GetIconPathByFamilyCategoryName(const std::wstring& categoryName)
{
    return ICON_FamilyCategory;
}

std::wstring GnufFamilyTreeNodeUtil::GetIconPathByFamilyName(const std::wstring& familyName)
{
    return ICON_Family;
}

std::wstring GnufFamilyTreeNodeUtil::GetIconPathByFamilyTypeName(const std::wstring& familyTypeName)
{
    return ICON_FamilyType;
}

std::wstring GnufFamilyTreeNodeUtil::GetIconPathForImportedObject()
{
    return ICON_ImportedObject;
}

std::wstring GnufFamilyTreeNodeUtil::GetIconPathForCADSheetCategory()
{
    return ICON_CADSheetCategory;
}

std::wstring GnufFamilyTreeNodeUtil::GetIconPathForCADSheet()
{
    return ICON_CADSheet;
}

void GnufFamilyTreeNodeUtil::RemoveSelectedFamlies(std::list<TreeNode*>& selectedItem, const std::wstring& cmdId)
{
    for (TreeNode*& item : selectedItem)
    {
        const gcmp::Any & userData = item->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);
        if (userData.empty()) continue;

        if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILY || userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_CAD_SHEET) //族节点
        {
            if (!gcmp::JournalUtils::IsInReplay())
            {
                if (!item->nodeInfo(0))
                {
                    continue;
                }

                std::wstring familyName = item->nodeInfo(0)->caption();

                gcmp::CommandParameters cmdParams;
                cmdParams[L"FamilyName"] = familyName;

                std::wstring strCmdId = cmdId;
                OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
                DBG_WARN_AND_CONTINUE_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
                opJournalCmdData->SetCommandName(strCmdId);
                opJournalCmdData->SetParameterArray(cmdParams);
                gcmp::JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));

                ICommandManager* pCmdMgr = ICommandManager::Get();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
                pCmdMgr->SendCommand(strCmdId, cmdParams);
            }
        }
    }
}

void GnufFamilyTreeNodeUtil::SaveFamilyAs(TreeNode* pTreeItem, const std::wstring& cmdId)
{
    if (pTreeItem == nullptr)
        return;

    const gcmp::Any & userData = pTreeItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);
    if (userData.empty()) return;

    if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILY || userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_CAD_SHEET) //族节点
    {
        IUiDocumentViewManager *pUiDocumentManager = IUiDocumentViewManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocumentManager, L"pUiDocumentManager 不存在", L"paramodel", L"2024-02-20");
        IUiDocument *pUiDocument = pUiDocumentManager->GetCurrentUiDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocument, L"pUiDocument 不存在", L"paramodel", L"2024-02-20");
        gcmp::IDocument* pDoc = pUiDocument->GetDbDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc不存在", L"paramodel", L"2024-02-20");
        const Info* pInfo = pTreeItem->nodeInfo(0);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pInfo, L"pInfo 不存在", L"paramodel", L"2024-02-20");
        std::wstring familyName = pInfo->caption();

        IFamilyConfigElement* pElement = IFamilyConfigElement::GetFamilyConfigElementByName(pDoc, familyName);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"FamilyConfigElement个数不对", L"paramodel", L"2024-02-20");

        if (!gcmp::JournalUtils::IsInReplay())
        {
            std::wstring strCmdId = cmdId;
            OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
            opJournalCmdData->SetCommandName(strCmdId);
            gcmp::JournalUtils::StartRecordCommand(TransferOwnership(opJournalCmdData));

            gcmp::CommandParameters cmdParams;
            cmdParams[L"FamilyName"] = pElement->GetFamilyFileName();

            ICommandManager* pCmdMgr = ICommandManager::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
            pCmdMgr->SendCommand(strCmdId, cmdParams);
        }
    }
}

void GnufFamilyTreeNodeUtil::LoadFamily(TreeNode* pTreeItem, const std::wstring& cmdId)
{
    if (pTreeItem == nullptr)
        return;

    const gcmp::Any & userData = pTreeItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);
    if (userData.empty()) return;

    if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILY_ROOT) //族节点
    {
        if (!gcmp::JournalUtils::IsInReplay())
        {
            std::wstring strCmdId = cmdId;
            OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
            opJournalCmdData->SetCommandName(strCmdId);
            gcmp::JournalUtils::StartRecordCommand(TransferOwnership(opJournalCmdData));

            ICommandManager* pCmdMgr = ICommandManager::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
            pCmdMgr->SendCommand(strCmdId);
        }
    }
}

void GnufFamilyTreeNodeUtil::EditFamily(TreeNode* pTreeItem, const std::wstring& cmdId)
{
    if (pTreeItem == nullptr)
        return;

    if (pTreeItem->nodeInfo(0) == nullptr)
    {
        return;
    }

    const gcmp::Any & userData = pTreeItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);
    if (userData.empty()) return;

    if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILY || userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_CAD_SHEET) //族节点
    {
        std::wstring familyName = pTreeItem->nodeInfo(0)->caption();

        if (!gcmp::JournalUtils::IsInReplay())
        {
            gcmp::CommandParameters cmdParams;
            cmdParams[L"FamilyInProjectContainer"] = true;
            cmdParams[L"FamilyName"] = familyName;

            std::wstring strCmdId = cmdId;
            OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
            opJournalCmdData->SetCommandName(strCmdId);
            opJournalCmdData->SetParameterArray(cmdParams);
            gcmp::JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));

            ICommandManager* pCmdMgr = ICommandManager::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
            pCmdMgr->SendCommand(strCmdId, cmdParams);
        }
    }
}

void GnufFamilyTreeNodeUtil::RenameFamily(TreeNode* pTreeItem, const std::wstring& cmdId)
{
    if (pTreeItem == nullptr)
        return;

    if (pTreeItem->nodeInfo(0) == nullptr)
    {
        return;
    }

    const gcmp::Any & userData = pTreeItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);
    if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILY) //族节点
    {
        if (!gcmp::JournalUtils::IsInReplay())
        {
            gcmp::CommandParameters cmdParams;
            cmdParams[L"FamilyName"] = pTreeItem->nodeInfo(0)->caption();

            std::wstring strCmdId = cmdId;
            OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
            opJournalCmdData->SetCommandName(strCmdId);
            opJournalCmdData->SetParameterArray(cmdParams);
            gcmp::JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));

            ICommandManager* pCmdMgr = ICommandManager::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
            pCmdMgr->SendCommand(strCmdId, cmdParams);
        }
    }
}

void GnufFamilyTreeNodeUtil::CreateFamilyInstance(TreeNode* pTreeItem, const std::wstring& cmdId)
{
    if (pTreeItem == nullptr)
        return;

    if (pTreeItem->nodeInfo(0) == nullptr)
    {
        return;
    }

    const gcmp::Any & userData = pTreeItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);
    if (userData.empty()) return;

    if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILYTYPE || userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_CAD_SHEET) //族类型节点
    {
        TreeNode* pParent = pTreeItem->parentNode();
        if (pParent != nullptr)
        {
            if (pParent->nodeInfo(0) == nullptr)
            {
                return;
            }

            if (!gcmp::JournalUtils::IsInReplay())
            {
                gcmp::CommandParameters cmdParams;
                if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILYTYPE)
                {
                    cmdParams[L"FamilyName"] = pParent->nodeInfo(0)->caption();
                    cmdParams[L"FamilyType"] = pTreeItem->nodeInfo(0)->caption();
                }
                else if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_CAD_SHEET)
                {
                    cmdParams[L"FamilyName"] = pTreeItem->nodeInfo(0)->caption();
                    const gcmp::Any & varFamilyType = pTreeItem->userDataAt(Gnuf_CAD_SHEET_ITEM_FAMILY_TYPE);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(!varFamilyType.empty() && varFamilyType.compatible(std::wstring()), L"无效参数", L"paramodel", L"2024-02-20");
                    cmdParams[L"FamilyType"] = varFamilyType.cast<std::wstring>();
                }

                std::wstring strCmdId = cmdId;
                OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
                DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
                opJournalCmdData->SetCommandName(strCmdId);
                opJournalCmdData->SetParameterArray(cmdParams);
                gcmp::JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));

                ICommandManager* pCmdMgr = ICommandManager::Get();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
                pCmdMgr->SendCommand(strCmdId, cmdParams);
            }
        }
    }
}

void GnufFamilyTreeNodeUtil::EditFamilyTypeParameter(TreeNode* pTreeItem)
{
    if (pTreeItem == nullptr)
        return;

    if (pTreeItem->nodeInfo(0) == nullptr)
    {
        return;
    }

    const gcmp::Any & typeData = pTreeItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);
    TreeNode* pParent = pTreeItem->parentNode();
    if (pParent != nullptr)
    {
        if (pParent->nodeInfo(0) == nullptr)
        {
            return;
        }

        if (typeData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_FAMILYTYPE) //族类型节点
        {
            if (!gcmp::JournalUtils::IsInReplay())
            {
                gcmp::CommandParameters cmdParams;
                cmdParams[L"FamilyName"] = pParent->nodeInfo(0)->caption();
                cmdParams[L"FamilyType"] = pTreeItem->nodeInfo(0)->caption();

                OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
                DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
                opJournalCmdData->SetCommandName(ID_CMD_FAMILY_EDIT_TYPE_PARAM);
                opJournalCmdData->SetParameterArray(cmdParams);
                gcmp::JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));

                ICommandManager* pCmdMgr = ICommandManager::Get();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr != nullptr, L"pCmdMgr为空", L"paramodel", L"2024-02-20");
                pCmdMgr->SendCommand(ID_CMD_FAMILY_EDIT_TYPE_PARAM, cmdParams);
            }
        }
    }
}

void gfam::GnufFamilyTreeNodeUtil::RemoveImportedObject(gnuf::TreeNode * pTreeItem, const std::wstring & cmdId)
{
    if (pTreeItem == nullptr)
        return;
    const gcmp::Any & userData = pTreeItem->userDataAt(Gnuf_FAMILY_USER_DATA_ROLE);

    auto lala = userData.cast<FamilyTreeNodeType>();
    if (userData.cast<FamilyTreeNodeType>() == FamilyTreeNodeType::TWNT_CAD_SHEET) // 导入对象节点
    {
        if (!gcmp::JournalUtils::IsInReplay())
        {
            std::wstring elementName = pTreeItem->nodeInfo(0)->caption();
            CommandParameters cmdParams;
            const std::wstring elementNameKey = L"CADElementName";
            cmdParams.emplace(elementNameKey, elementName);

            OwnerPtr<gcmp::IJournalCommandData> opJournalCmdData = IJournalCommandData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opJournalCmdData, L"CREATE_JOURNAL_DATA(IJournalCommandData, JOURNAL_COMMAND_DATA)返回空指针", L"paramodel", L"2024-02-20");
            opJournalCmdData->SetCommandName(cmdId);
            opJournalCmdData->SetParameterArray(cmdParams);
            gcmp::JournalUtils::RecordCommand(TransferOwnership(opJournalCmdData));

            ICommandManager* pCmdMgr = ICommandManager::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr, L"invalid pCmdMgr", L"paramodel", L"2024-02-20");
            pCmdMgr->SendCommand(cmdId, cmdParams);
        }
    }

}
